package com.zmj.sy.mom.srv.aps.service.scheduler.extractor;

import cn.hutool.core.lang.Assert;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.service.scheduler.order.DefaultBom;
import com.zmj.sy.mom.srv.aps.service.scheduler.order.DefaultOrder;
import com.zmj.sy.mom.srv.aps.service.scheduler.order.DefaultPhase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class OrderExtractor {

    private final OrderMapper orderMapper;

    private final OrderBomMapper orderBomMapper;

    private final OrderPhaseMapper orderPhaseMapper;

    private final ReverseOrderMapper reverseOrderMapper;

    private final ApsOrderMapper apsOrderMapper;

    public List<DefaultOrder> load(Set<Integer> orderIds) {
        // 基础订单信息
        Assert.notEmpty(orderIds, "未提供可排产订单");
        List<Order> orders = orderMapper.selectBatchIds(orderIds);
        Assert.notEmpty(orders, "未查询到可排产订单");
        List<Integer> orderIdList = orders.stream().map(Order::getId).collect(Collectors.toList());

        // 订单拆单信息
        List<ReverseOrder> reverseOrders = reverseOrderMapper.lambdaQuery()
                .in(ReverseOrder::getOrderId, orderIdList)
                .isNotNull(ReverseOrder::getParentId)
                .list();
        Map<Integer, List<ReverseOrder>> reverseOrderMap = reverseOrders.stream()
                .collect(Collectors.groupingBy(ReverseOrder::getOrderId));

        List<ApsOrder> apsOrders = apsOrderMapper.lambdaQuery()
                .in(ApsOrder::getOrderId, orderIdList)
                .list();
        Map<Integer, List<ApsOrder>> apsOrderMap = apsOrders.stream()
                .collect(Collectors.groupingBy(ApsOrder::getOrderId));

        // 订单 BOM 信息
        List<OrderBom> bomList = orderBomMapper.lambdaQuery()
                .in(OrderBom::getOrderId, orderIdList)
                .list();
        Map<Integer, List<OrderBom>> bomOrderIdMap = bomList.stream()
                .collect(Collectors.groupingBy(OrderBom::getOrderId));

        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .in(OrderPhase::getOrderId, orderIdList)
                .list();
        Map<Integer, Map<Integer, List<OrderPhase>>> phaseOrderIdMap = phaseList.stream()
                .collect(Collectors.groupingBy(OrderPhase::getOrderId,
                        Collectors.groupingBy(OrderPhase::getBomId)));

        return orders.stream()
                .map(order -> {
                    List<ReverseOrder> reverseOrdersOfOrder = reverseOrderMap.getOrDefault(order.getId(), new ArrayList<>());
                    List<ApsOrder> apsOrdersOfOrder = apsOrderMap.getOrDefault(order.getId(), new ArrayList<>());
                    List<OrderBom> bomListOfOrder = bomOrderIdMap.getOrDefault(order.getId(), new ArrayList<>());
                    Map<Integer, List<OrderPhase>> phaseMapOfOrder = phaseOrderIdMap.getOrDefault(order.getId(), new HashMap<>());
                    return buildOrder(order, reverseOrdersOfOrder, apsOrdersOfOrder, bomListOfOrder, phaseMapOfOrder);
                })
                .collect(Collectors.toList());
    }

    private static DefaultOrder buildOrder(Order order,
                                           List<ReverseOrder> reverseOrders,
                                           List<ApsOrder> apsOrders,
                                           List<OrderBom> bomList,
                                           Map<Integer, List<OrderPhase>> phaseMap) {
        DefaultOrder defaultOrder = new DefaultOrder();
        defaultOrder.setOrder(order);
        defaultOrder.setReverseOrders(reverseOrders);
        defaultOrder.setApsOrders(apsOrders);
        defaultOrder.setBomList(new ArrayList<>());
        defaultOrder.setPhaseList(new ArrayList<>());

        Map<Integer, DefaultBom> bomMap = new HashMap<>();
        Map<Integer, List<DefaultBom>> childrenMap = new HashMap<>();
        for (OrderBom orderBom : bomList) {
            DefaultBom bom = new DefaultBom();
            bom.setBom(orderBom);
            bom.setPhases(new ArrayList<>());
            bom.setOrder(defaultOrder);
            bomMap.put(orderBom.getId(), bom);
            int pid = orderBom.getPid() != null ? orderBom.getPid() : 0;
            childrenMap.computeIfAbsent(pid, k -> new ArrayList<>()).add(bom);
            defaultOrder.getBomList().add(bom);
        }
        for (DefaultBom bom : defaultOrder.getBomList()) {
            bom.setChildren(childrenMap.getOrDefault(bom.getBom().getId(), new ArrayList<>()));
            int pid = bom.getBom().getPid() != null ? bom.getBom().getPid() : 0;
            bom.setParent(bomMap.get(pid));
        }

        phaseMap.forEach((bomId, phaseList) -> {
            DefaultBom bom = bomMap.get(bomId);
            phaseList.sort(Comparator.comparingInt(OrderPhase::getPhaseSeq));
            for (OrderPhase phase : phaseList) {
                DefaultPhase defaultPhase = new DefaultPhase();
                defaultPhase.setPhase(phase);
                defaultPhase.setBom(bom);
                defaultOrder.getPhaseList().add(defaultPhase);
                bom.getPhases().add(defaultPhase);
            }
        });

        return defaultOrder;
    }

}
